#include <stdlib.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>

#define MAXLINE 5
#define OPEN_MAX 100
#define LISTENQ 20
#define SERV_PORT 5000
#define INFTIM 1000

void setnonblocking(int sock)
{
	int opts;
	opts = fcntl (sock,F_GETFL);
	if (opts < 0) 
	{
		perror("fcntl(sock,GETFL)");
		exit(1);
	}
	opts = opts|O_NONBLOCK;
	if(fcntl(sock,F_SETFL,opts) <0)
	{
		perror("fcntl(sock,SETFL,opts)");
		exit(1);
	}
	
}


int main(int argc ,char *argv[])
{
	int i,maxi,listenfd,connfd,sockfd,epfd,portnumber,nfds;
	ssize_t n;
	char line[MAXLINE];
	socklen_t clilen;
	printf("%d \n",argc);
	if (2 == argc)
	{
		if ((portnumber = atoi(argv[1])) <=0)
		{
			fprintf(stderr,"Usage: %s portnumber \a\n",argv[0]);
			return 1;
	
		}	
		fprintf(stdout,"%d \n",portnumber);
	}
	else
	{
		fprintf(stderr,"Usage: %s portnumber \a\n",argv[0]);
		return 1;
	}
	struct epoll_event ev,events[20];
	epfd = epoll_create(256);
	struct sockaddr_in clienaddr;
	struct sockaddr_in serveraddr;
	listenfd = socket(AF_INET,SOCK_STREAM,0);
	ev.data.fd = listenfd;
	ev.events = EPOLLIN|EPOLLET;
	epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);
	bzero(&serveraddr,sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;
	char *local_addr = "127.0.0.1";
	inet_aton(local_addr,&(serveraddr.sin_addr));

	serveraddr.sin_port = htons(portnumber);
	bind(listenfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
	listen(listenfd,LISTENQ);
	maxi =0;
	for(;;){
		nfds = epoll_wait(epfd,events,20,500);
		for(i=0;i<nfds;++i)
		{
			if (events[i].data.fd == listenfd)
			{
				connfd = accept(listenfd,(struct sockaddr *)&clienaddr,&clilen);
				if(connfd < 0){
					perror("connfd < 0");
					exit(1);
				}
				char *str = inet_ntoa(clienaddr.sin_addr);
				fprintf(stdout,"accapt a connection from %s \n",str);
				ev.data.fd = connfd;
				ev.events =EPOLLIN|EPOLLET;
				epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
			}
			else if(events[i].events&EPOLLIN)
			{
				fprintf(stdout,"EPOLLIN  \n");
				if (( sockfd = events[i].data.fd) < 0)
					continue;
				if ((n = read(sockfd,line,MAXLINE)) <0) {
					if (errno ==ECONNRESET) {
						close(sockfd);
						events[i].data.fd = -1;
					}
					else fprintf(stdout,"read %s\n",line);

					ev.data.fd = sockfd;
					ev.events = EPOLLOUT|EPOLLET;



				}
				else if (events[i].events&EPOLLOUT)
				{
					sockfd = events[i].data.fd;
					write(sockfd,line,n);
					ev.data.fd = sockfd;
					ev.events = EPOLLIN|EPOLLET;
					epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
				}
			}
		}
	}
	return 0;
}
